package com.sunfeng.n8;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;

/**
 * 测试ForkJoinPool
 *
 * @author sunfeng
 * @date 2021/04/21 10:26
 **/
public class TestForkJoin {
    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool(3);
//        MyTask myTask = new MyTask(5);
//        Integer invoke = forkJoinPool.invoke(myTask);
//        System.out.println(invoke);
        System.out.println(forkJoinPool.invoke(new MyTask2(1, 10)));

    }
}

@Slf4j(topic = "c.MyTask")
class MyTask extends RecursiveTask<Integer> {
    private int n;

    public MyTask(int n) {
        this.n = n;
    }

    @Override
    public String toString() {
        return "{" + n + '}';
    }

    @Override
    protected Integer compute() {
        if (n == 1) {
            log.debug("join() {}", n);
            return 1;
        }
        MyTask t1 = new MyTask(n - 1);
        t1.fork();
        log.debug("fork() {} + {}", n, t1);
        // 模拟每次执行消耗的时间  这样可以体现出分治的优点
        try {
            TimeUnit.SECONDS.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        int result = n + t1.join();
        log.debug("join() {} + {} = {}", n, t1, result);
        return result;
    }
}
@Slf4j(topic = "c.MyTask2")
class MyTask2 extends RecursiveTask<Integer> {
    int begin;
    int end;

    public MyTask2(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    public String toString() {
        return "{" +
                begin + "," +
                end +
                '}';
    }

    @Override
    protected Integer compute() {

        // 设置阈值
        if (begin == end) {
            log.debug("join() {}", begin);
            return begin;
        }
        if (end - begin == 1) {
            log.debug("join() {} + {} = {}", begin, end, end + begin);
            return end + begin;
        }


        // 1 5
        int mid = (end + begin) / 2; // 3
        try {
            TimeUnit.SECONDS.sleep(mid);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 任务拆分
        MyTask2 t1 = new MyTask2(begin, mid); // 1,3
        t1.fork();
        MyTask2 t2 = new MyTask2(mid + 1, end); // 4,5
        t2.fork();
        log.debug("fork() {} + {} = ?", t1, t2);
        int result = t1.join() + t2.join();
        log.debug("join() {} + {} = {}", t1, t2, result);
        return result;
    }
}